Skip to content

modules: fix sync hook short-circuit in require() in imported CJS - #62920

Merged
nodejs-github-bot merged 1 commit into
nodejs:mainfrom
joyeecheung:fix-hooks
May 7, 2026
Merged

nodejs-github-bot merged 1 commit into
nodejs:mainfrom
joyeecheung:fix-hooks

Conversation

@joyeecheung

@joyeecheung joyeecheung commented Apr 23, 2026 •

Copy link
Copy Markdown
Member
  • For imported CJS, if it's not customized by asynchronous hooks, make sure it won't use the quirky re-invented require in all cases.
  • When the imported CJS module is customized by synchronous hooks, in the synthetic module evalutation step, avoid calling the respective default step again.
  • Make the branching of loadCJSModuleWithModuleLoad() and loadCJSModuleWithSpecialRequire() more explicit, and fold the tentative fs read in the 'commonjs' translator into the share createCJSModuleWrap() helper instead of checking it twice in the same path.

Refs: #55808 (comment)
Fixes: #63060

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/loaders

@nodejs-github-bot nodejs-github-bot added esm Issues and PRs related to the ECMAScript Modules implementation. module Issues and PRs related to the module subsystem. needs-ci PRs that need a full CI run. labels Apr 23, 2026
@joyeecheung

Copy link
Copy Markdown
Member Author

@codecov

codecov Bot commented Apr 24, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.66071% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.65%. Comparing base (13e90d0) to head (539c680).
⚠️ Report is 52 commits behind head on main.

Files with missing lines Patch % Lines
lib/internal/test_runner/mock/mock.js 87.50% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #62920      +/-   ##
==========================================
- Coverage   91.49%   89.65%   -1.84%     
==========================================
  Files         360      712     +352     
  Lines      151674   220633   +68959     
  Branches    23919    42293   +18374     
==========================================
+ Hits       138772   197815   +59043     
- Misses      12625    14662    +2037     
- Partials      277     8156    +7879     
Files with missing lines Coverage Δ
lib/internal/modules/cjs/loader.js 98.27% <100.00%> (+19.07%) ⬆️
lib/internal/modules/esm/load.js 91.40% <ø> (+7.70%) ⬆️
lib/internal/modules/esm/loader.js 99.71% <100.00%> (+40.24%) ⬆️
lib/internal/modules/esm/translators.js 97.51% <100.00%> (+5.99%) ⬆️
lib/internal/test_runner/mock/mock.js 98.54% <87.50%> (+0.22%) ⬆️

... and 471 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@joyeecheung
joyeecheung force-pushed the fix-hooks branch 3 times, most recently from 1ef6e6e to 53673f3 Compare April 24, 2026 22:59
@joyeecheung joyeecheung added request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. review wanted PRs that need review. and removed request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. labels May 1, 2026
@joyeecheung joyeecheung added the request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. label May 1, 2026
@github-actions github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. label May 1, 2026
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

@DivyanshuX9

DivyanshuX9 commented May 1, 2026 •

Copy link
Copy Markdown
Contributor

Why still some test fails is it a issue in code or it just cope(some infra issue) ?

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

@joyeecheung

joyeecheung commented May 1, 2026 •

Copy link
Copy Markdown
Member Author

It's just regular flake. In the past ~8 years it would be miracle for a PR to pass the CI fully without a flake 😬 https://github.com/nodejs/reliability/issues

@joyeecheung joyeecheung added the commit-queue PRs queued for automated landing through the Commit Queue. label May 1, 2026
@nodejs-github-bot nodejs-github-bot added commit-queue-failed PRs whose Commit Queue landing failed and need manual intervention before retrying. and removed commit-queue PRs queued for automated landing through the Commit Queue. labels May 1, 2026
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator
Commit Queue failed
- Loading data for nodejs/node/pull/62920
✔  Done loading data for nodejs/node/pull/62920
----------------------------------- PR info ------------------------------------
Title      modules: fix sync hook short-circuit in require() in imported CJS (#62920)
Author     Joyee Cheung <joyeec9h3@gmail.com> (@joyeecheung)
Branch     joyeecheung:fix-hooks -> nodejs:main
Labels     module, esm, needs-ci, review wanted
Commits    1
 - module: fix sync hook short-circuit in require() in imported CJS
Committers 1
 - Joyee Cheung <joyeec9h3@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/62920
Fixes: https://github.com/nodejs/node/issues/63060
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
------------------------------ Generated metadata ------------------------------
PR-URL: https://github.com/nodejs/node/pull/62920
Fixes: https://github.com/nodejs/node/issues/63060
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
--------------------------------------------------------------------------------
   ℹ  This PR was created on Thu, 23 Apr 2026 22:07:13 GMT
   ✔  Approvals: 1
   ✔  - Paolo Insogna (@ShogunPanda) (TSC): https://github.com/nodejs/node/pull/62920#pullrequestreview-4211272383
   ✔  Last GitHub CI successful
   ℹ  Last Full PR CI on 2026-05-01T16:34:45Z: https://ci.nodejs.org/job/node-test-pull-request/73060/
- Querying data for job/node-test-pull-request/73060/
✔  Build data downloaded
   ✔  Last Jenkins CI successful
--------------------------------------------------------------------------------
   ✔  No git cherry-pick in progress
   ✔  No git am in progress
   ✔  No git rebase in progress
--------------------------------------------------------------------------------
- Bringing origin/main up to date...
From https://github.com/nodejs/node
 * branch                  main       -> FETCH_HEAD
✔  origin/main is now up-to-date
- Downloading patch for 62920
From https://github.com/nodejs/node
 * branch                  refs/pull/62920/merge -> FETCH_HEAD
✔  Fetched commits as 9c0101860e77..53673f349d9a
--------------------------------------------------------------------------------
Auto-merging lib/internal/modules/cjs/loader.js
Auto-merging lib/internal/modules/esm/loader.js
[main a31ccfd3be] module: fix sync hook short-circuit in require() in imported CJS
 Author: Joyee Cheung <joyeec9h3@gmail.com>
 Date: Sat Apr 18 22:10:36 2026 +0100
 6 files changed, 265 insertions(+), 89 deletions(-)
 create mode 100644 test/module-hooks/test-module-hooks-load-import-cjs-custom-source.js
   ✔  Patches applied
--------------------------------------------------------------------------------
--------------------------------- New Message ----------------------------------
module: fix sync hook short-circuit in require() in imported CJS
  • For imported CJS, if it's not customized by asynchronous hooks,
    make sure it won't use the quirky re-invented require in all
    cases.
  • When the imported CJS module is customized by synchronous hooks,
    in the synthetic module evalutation step, avoid calling the
    respective default step again.
  • Make the branching of loadCJSModuleWithModuleLoad() and
    loadCJSModuleWithSpecialRequire() more explicit, and fold
    the tentative fs read in the 'commonjs' translator into the
    share createCJSModuleWrap() helper instead of checking it
    twice in the same path.

PR-URL: #62920
Fixes: #63060
Reviewed-By: Paolo Insogna <paolo@cowtech.it>

[main ec616a5410] module: fix sync hook short-circuit in require() in imported CJS
Author: Joyee Cheung <joyeec9h3@gmail.com>
Date: Sat Apr 18 22:10:36 2026 +0100
6 files changed, 265 insertions(+), 89 deletions(-)
create mode 100644 test/module-hooks/test-module-hooks-load-import-cjs-custom-source.js
✖ ec616a5410d84de7daae16810ac0f22f8c70a933
✔ 0:0 no Assisted-by metadata assisted-by-is-trailer
✔ 0:0 no Co-authored-by metadata co-authored-by-is-trailer
✔ 14:7 Valid fixes URL. fixes-url
✔ 0:0 blank line after title line-after-title
✔ 0:0 line-lengths are valid line-length
✔ 0:0 metadata is at end of message metadata-end
✔ 13:8 PR-URL is valid. pr-url
✔ 0:0 reviewers are valid reviewers
✖ 0:0 Commit must have a "Signed-off-by" trailer signed-off-by
✔ 0:0 valid subsystems subsystem
✔ 0:0 Title is formatted correctly. title-format
⚠ 0:50 Title should be <= 50 columns. title-length

ℹ Please fix the commit message and try again.
Please manually ammend the commit message, by running
git commit --amend
Once commit message is fixed, finish the landing command running
git node land --continue

https://github.com/nodejs/node/actions/runs/25235870883

@mcollina mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@DivyanshuX9

Copy link
Copy Markdown
Contributor

I think the issue related must be closed #63060 by now.

@DivyanshuX9

DivyanshuX9 commented May 2, 2026 •

Copy link
Copy Markdown
Contributor

Btw @joyeecheung , should i look into the flaky test cases and try resolving them so that after 8 year someone might get the miracle done ;)

cjnoname added a commit to documonster/documonster that referenced this pull request Sep 15, 2026
… invalidated

vitest 4 → 5, pnpm 11 → 12, @oxc-node/core 0.1.0 → 0.1.2, oxfmt 0.64 → 0.68,
oxlint 1.79 → 1.83, @rspack/core 2.1 → 2.2, rolldown 1.2.5 → 1.2.8, playwright
1.62 → 1.63, plus @types/node and fast-xml-parser.

`@oxc-node/core` 0.1.2 does not remove the need for the patch: `register.mjs` is
byte-identical from 0.1.0 through 0.1.2 and on upstream `main` — verified with
`cmp`, both at blob 9658531 — and the 0.1.1/0.1.2 changelogs only cover
transform, resolve and UNC-path fixes. Dropping the patch brought DEP0205 back to
every `node --import @oxc-node/core/register`, which is every gate script here.

The patch is rebuilt rather than re-keyed, because the old one was wrong in a way
this package never exercised: it routed a CommonJS `require()` into oxc's
resolver, which rejects a context without `importAttributes`, so any `.ts` entry
in a `"type": "commonjs"` scope died with ``Missing field `importAttributes` ``.
Nothing here is CommonJS, so it never showed. The replacement keeps `require()`
on Node's own resolution, hands a file oxc reports as CommonJS back to the
`pirates` hook so its source map stays accurate, and gates `registerHooks` on
Node >= 26.2 — it exists from 22.15 but only became a complete replacement once
nodejs/node#59011 (24.5.0, backported to 22.19.0) and nodejs/node#62920 (26.2.0)
landed. Below that the deprecated path still runs, so nothing regresses.
Measured across 34 release binaries from 22.14.0 to 26.8.2. Submitted upstream as
oxc-project/oxc-node#764.

The satellite's shared devDependencies move to a pnpm catalog. It had been left
on vitest 4 while the root went to 5, which put two vitest majors in the tree;
declaring the version once makes that drift structurally impossible, and
`pnpm pack` rewrites `catalog:` to a real range so a consumer never sees it.

`allowBuilds.esbuild` is now false. esbuild is still used — `scripts/treeshake-
verify.ts` is one of its three bundlers — but its postinstall only speeds up the
`esbuild` CLI, which nothing here invokes; the JS API spawns the platform binary
directly. `buildSync` and all 111 treeshake scenarios pass without it.

The two stream tests are reformatted by oxfmt 0.68, which breaks a trailing
function expression's parameters differently. No behaviour change.

Verified: 20397 node tests, 14454 browser tests, 592 satellite tests, `pnpm
check`, and `pnpm verify:treeshake` 111/111.
cjnoname added a commit to cjnoname/oxc-node that referenced this pull request Sep 18, 2026
Two requests the asynchronous `module.register()` never showed the hooks reach them
under `module.registerHooks()`, and both regressed:

- Its default load is synchronous and always reads the file, so a `commonjs` result
  arrives with its bytes attached — including for a `.node` addon, which resolves as
  `commonjs`, and for a latin-1 CommonJS file. `transform_output` then failed to decode
  them ("Failed to convert Uint8Array to Vec<u8>"), so `import addon from './x.node'`
  crashed where it printed an object before. Hand such a source back the way the
  asynchronous default load did — no source, CommonJS machinery reads the file — instead
  of propagating the decode error.
- `require()` was told apart by the `require` export condition, but `--conditions`
  appends its values to *every* request: under `--conditions=require` an extensionless
  `import` failed with ERR_MODULE_NOT_FOUND and a CommonJS-reported file with ESM syntax
  with ERR_REQUIRE_CYCLE_MODULE, and `--conditions=import` is the mirror hazard.
  Discriminate on `importAttributes` instead — the field the native hooks require anyway,
  absent on every CommonJS context and present, if empty, on every ESM one.

The load hook now returns `{ source: null }` for a CommonJS result rather than calling
`nextLoad` a second time: same outcome, one file read and one transform less, and it is
the shape that never trips nodejs/node#62920, so that defect no longer bears on the
version floor — v26.2.0 is kept as a deliberate margin. CI gains a Node.js 26 job, since
nothing in the matrix exercised the synchronous path.
Brooooooklyn added a commit to oxc-project/oxc-node that referenced this pull request Sep 18, 2026
## Problem

`packages/core/register.mjs` calls `module.register()`. Node.js
runtime-deprecated that
API in **v25.9.0**
([DEP0205](https://nodejs.org/api/deprecations.html#DEP0205)), so every
`node --import @oxc-node/core/register` now prints:

```
(node:94305) [DEP0205] DeprecationWarning: `module.register()` is deprecated. Use `module.registerHooks()` instead.
```

This is not only cosmetic — **`pnpm test` already fails on Node.js 26**
on `main`, because
four tests assert an empty stderr and the warning lands there. CI runs
Node 22 and 24
only, so it has stayed invisible:

```
# main, unmodified, Node v26.8.1
 Test Files  2 failed | 7 passed | 1 skipped (10)
      Tests  4 failed | 70 passed | 7 skipped (81)

 FAIL  __tests__/stdin-tty.spec.ts > CLI properly handles stdin piping
 FAIL  __tests__/tsconfig-discovery.spec.ts > a broken project reference in an ancestor that does not own the file breaks nothing
 FAIL  __tests__/tsconfig-discovery.spec.ts > tsconfig paths apply to JavaScript importers with allowJs unset
 FAIL  __tests__/tsconfig-discovery.spec.ts > a project directory with a space and non-ASCII characters still resolves
```

All four are the same diff: `+ (node:1427) [DEP0205] DeprecationWarning:
...`

## Change

Use the synchronous, in-thread `module.registerHooks()` where it is
complete, and keep
`module.register()` everywhere else. The ESM path is otherwise unchanged
— `resolve` still
hands everything to `createResolve` and `load` to `oxcLoad`, exactly as
`esm.mjs` does.

Three things make this more than a one-line swap. Each was measured
against release
binaries rather than reasoned about, and a naive replacement fails on
all three.

### 1. `registerHooks()` shows `require()` to the hooks; `register()`
never did

The CommonJS resolve/load context carries **no `importAttributes`**, and
both
`createResolve` and `load` reject a context without it:

```
Error: Missing field `importAttributes`
    at resolve (.../register.mjs:11:12)
    at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1217:25)
```

So a request whose `conditions` contain `require` goes to
`nextResolve`/`nextLoad`.
Node.js resolves those correctly by itself, because the `pirates` hook
has put the
TypeScript extensions into `Module._extensions` — that is what lets its
CommonJS resolver
complete `require('./dep')` to `./dep.ts` and `require('./sub')` to
`./sub/index.ts`.

### 2. A file that oxc-node settles on as CommonJS must go back to
`nextLoad`

Otherwise the `pirates` hook no longer produces the inline source map,
and stack trace
precision regresses. `cli.spec.ts` covers exactly this:

| | reported location |
|---|---|
| `module.register()` | `stacktrace-cjs.cts:6:12` ✅ |
| naive `registerHooks()` | `stacktrace-cjs.cts:5:10` ❌ |

Calling `oxcLoad` **first** and only then deferring is what keeps #759
intact — a
CommonJS-reported file that actually contains ESM syntax still runs as
an ES module.

### 3. `registerHooks` needs a version floor, not a `typeof` check

It exists from v22.15.0/v23.5.0, but two defects had to be fixed first.
Bisected over
every available minor:

| Node.js | ESM importing a CJS package | `require()` in an imported CJS
entry |
|---|---|---|
| 22.14.0 (no `registerHooks`) | — fallback | — fallback |
| 22.15.0 – 22.18.0 | ❌ | ❌ |
| 22.19.0 – 22.22.1 | ✅ | ❌ |
| 23.5.0 – 23.11.1 (EOL) | ❌ | ❌ |
| 24.0.0 – 24.4.1 | ❌ | ❌ |
| 24.5.0 – 25.9.0 | ✅ | ❌ |
| 26.0.0 – 26.1.0 | ✅ | ❌ |
| **26.2.0+** | ✅ | ✅ |

Those boundaries are not arbitrary — they match the Node.js fixes
exactly:

- **[nodejs/node#59011](nodejs/node#59011
*"module: fix conditions
override in synchronous resolve hooks"* — v24.5.0 (`fe0195fdcc`),
backported to v22.19.0
(`0eec5cc492`), never backported to the end-of-life 23.x line. Without
it,
`import { jsx } from 'react/jsx-runtime'` fails with *does not provide
an export named 'jsx'*.
- **[nodejs/node#62920](nodejs/node#62920
*"module: fix sync hook
short-circuit in require() in imported CJS"* — v26.2.0 (`96f19a16d0`).
Without it, a `.ts`
  entry in a CommonJS package cannot `require()` its own files.

Hence the floor is **v26.2.0**. Below it the fallback runs and nothing
changes for those
runtimes; v26.0/v26.1 keep the warning, which is the honest outcome
given the defect.

## Verification

**34 release binaries**, v22.14.0 → v26.8.2 (every available
22.x/23.x/24.x/25.x/26.x
minor), against three fixtures: a CommonJS `require()` tree
(extensionless `.ts`,
directory `index.ts`, explicit `.cts`), an ESM tree (extensionless,
`.mts`, tsconfig
`paths`, `.tsx` + `react/jsx-runtime`), and a `createRequire` tree.

```
versions tested: 34
failures:        0
still warning:   26.0.0 26.1.0
```

Upstream suite, same machine, Node v26.8.1:

| | result |
|---|---|
| `main` | `4 failed | 70 passed` |
| this PR | **`75 passed`** |

`vp fmt` and `vp lint` are clean.

## Test added

`require()` completing an extensionless TypeScript specifier had no
coverage. The new case
in `cjs-esm-syntax.spec.ts` fails with `Cannot find module './dep'` if
the `pirates` hook
stops registering those extensions — verified by removing it.

---------

Co-authored-by: LongYinan <lynweklm@gmail.com>
inferno-chromium added a commit to tokenfuzz/tokenfuzz that referenced this pull request Sep 23, 2026
…script

compilerFor required typescript through the hooks it registers, so a failed
lookup from a .ts file asked for the compiler again before the cache held an
entry, until the stack overflowed. A bare catch swallowed the RangeError on
arm64, where the suite passed; amd64 Node 22 aborted in V8's regexp compiler
instead. The entry is now settled before the require, and the catches rethrow
anything but a resolution failure, so a recurrence fails on every host.

Node before 24.18 and 26.2 gives CommonJS that an ES module imported a
require() that skips module hooks (nodejs/node#62920). The alias test now
runs through a CommonJS entry on every hook-capable Node, the ES module entry
runs only where Node has the fix, and the guide says so. CI prints each host
lane's Node: the ubuntu runners use their image's Node 22, not the distro's.
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 12, 2026
The fix shipped in 26.2.0 and was backported to 24.18.0, not to 22.x.
Since the oxc-node#820 sync, the in-thread hooks return CommonJS source
that another hook supplied, so record the releases where require()
inside such a module can still fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 13, 2026
The fix shipped in 26.2.0 and was backported to 24.18.0, not to 22.x.
Since the oxc-node#820 sync, the in-thread hooks return CommonJS source
that another hook supplied, so record the releases where require()
inside such a module can still fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 13, 2026
The fix shipped in 26.2.0 and was backported to 24.18.0, not to 22.x.
Since the oxc-node#820 sync, the in-thread hooks return CommonJS source
that another hook supplied, so record the releases where require()
inside such a module can still fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 13, 2026
The fix shipped in 26.2.0 and was backported to 24.18.0, not to 22.x.
Since the oxc-node#820 sync, the in-thread hooks return CommonJS source
that another hook supplied, so record the releases where require()
inside such a module can still fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 13, 2026
The fix shipped in 26.2.0 and was backported to 24.18.0, not to 22.x.
Since the oxc-node#820 sync, the in-thread hooks return CommonJS source
that another hook supplied, so record the releases where require()
inside such a module can still fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 14, 2026
The fix shipped in 26.2.0 and was backported to 24.18.0, not to 22.x.
Since the oxc-node#820 sync, the in-thread hooks return CommonJS source
that another hook supplied, so record the releases where require()
inside such a module can still fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 14, 2026
The fix shipped in 26.2.0 and was backported to 24.18.0, not to 22.x.
Since the oxc-node#820 sync, the in-thread hooks return CommonJS source
that another hook supplied, so record the releases where require()
inside such a module can still fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 14, 2026
The fix shipped in 26.2.0 and was backported to 24.18.0, not to 22.x.
Since the oxc-node#820 sync, the in-thread hooks return CommonJS source
that another hook supplied, so record the releases where require()
inside such a module can still fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 15, 2026
Guide: collect every difference that can need a change when moving from
tsx into one section: `paths` outside `include`, the JSX default and lone
`@jsxImportSource`, `.cts` files with module syntax, the Node.js range,
watch mode, eval and the REPL, `node --import tsx`, and other loaders.

RFC:
- Known Limitations: the in-thread window without nodejs/node#62920, and
  the project-local bin not forwarding a SIGINT sent to it alone.
- A CLI/loader contract change gets new entry file names, so an unaware
  `vp` falls back to the global loader.
- Source maps for node_modules, and their startup cost.
- Security: project code provides the loader, as for `vp` delegation.
- The daily upgrade can stay red while oxc-node needs a newer oxc than
  Rolldown.
- Phase 2 migrates tsx only, gated on the Node.js range.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 15, 2026
The fix shipped in 26.2.0 and was backported to 24.18.0, not to 22.x.
Since the oxc-node#820 sync, the in-thread hooks return CommonJS source
that another hook supplied, so record the releases where require()
inside such a module can still fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 15, 2026
Guide: collect every difference that can need a change when moving from
tsx into one section: `paths` outside `include`, the JSX default and lone
`@jsxImportSource`, `.cts` files with module syntax, the Node.js range,
watch mode, eval and the REPL, `node --import tsx`, and other loaders.

RFC:
- Known Limitations: the in-thread window without nodejs/node#62920, and
  the project-local bin not forwarding a SIGINT sent to it alone.
- A CLI/loader contract change gets new entry file names, so an unaware
  `vp` falls back to the global loader.
- Source maps for node_modules, and their startup cost.
- Security: project code provides the loader, as for `vp` delegation.
- The daily upgrade can stay red while oxc-node needs a newer oxc than
  Rolldown.
- Phase 2 migrates tsx only, gated on the Node.js range.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 15, 2026
Node.js 22.22.3 and later use module.registerHooks(), decided by a
separate branch of canRegisterSyncHooks, and 22.x never gets
nodejs/node#62920, but no fixture ran that combination: the main fixture
pins 22.18 (module.register()) and the others 24.12 and 26.5. Add a
Node.js 22.23.2 fixture with the same steps as the 24.12 one, which on
22.x also lowers `using` to a runtime helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 15, 2026
The fix shipped in 26.2.0 and was backported to 24.18.0, not to 22.x.
Since the oxc-node#820 sync, the in-thread hooks return CommonJS source
that another hook supplied, so record the releases where require()
inside such a module can still fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 15, 2026
Guide: collect every difference that can need a change when moving from
tsx into one section: `paths` outside `include`, the JSX default and lone
`@jsxImportSource`, `.cts` files with module syntax, the Node.js range,
watch mode, eval and the REPL, `node --import tsx`, and other loaders.

RFC:
- Known Limitations: the in-thread window without nodejs/node#62920, and
  the project-local bin not forwarding a SIGINT sent to it alone.
- A CLI/loader contract change gets new entry file names, so an unaware
  `vp` falls back to the global loader.
- Source maps for node_modules, and their startup cost.
- Security: project code provides the loader, as for `vp` delegation.
- The daily upgrade can stay red while oxc-node needs a newer oxc than
  Rolldown.
- Phase 2 migrates tsx only, gated on the Node.js range.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 15, 2026
Node.js 22.22.3 and later use module.registerHooks(), decided by a
separate branch of canRegisterSyncHooks, and 22.x never gets
nodejs/node#62920, but no fixture ran that combination: the main fixture
pins 22.18 (module.register()) and the others 24.12 and 26.5. Add a
Node.js 22.23.2 fixture with the same steps as the 24.12 one, which on
22.x also lowers `using` to a runtime helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 15, 2026
The fix shipped in 26.2.0 and was backported to 24.18.0, not to 22.x.
Since the oxc-node#820 sync, the in-thread hooks return CommonJS source
that another hook supplied, so record the releases where require()
inside such a module can still fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 15, 2026
Guide: collect every difference that can need a change when moving from
tsx into one section: `paths` outside `include`, the JSX default and lone
`@jsxImportSource`, `.cts` files with module syntax, the Node.js range,
watch mode, eval and the REPL, `node --import tsx`, and other loaders.

RFC:
- Known Limitations: the in-thread window without nodejs/node#62920, and
  the project-local bin not forwarding a SIGINT sent to it alone.
- A CLI/loader contract change gets new entry file names, so an unaware
  `vp` falls back to the global loader.
- Source maps for node_modules, and their startup cost.
- Security: project code provides the loader, as for `vp` delegation.
- The daily upgrade can stay red while oxc-node needs a newer oxc than
  Rolldown.
- Phase 2 migrates tsx only, gated on the Node.js range.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 15, 2026
Node.js 22.22.3 and later use module.registerHooks(), decided by a
separate branch of canRegisterSyncHooks, and 22.x never gets
nodejs/node#62920, but no fixture ran that combination: the main fixture
pins 22.18 (module.register()) and the others 24.12 and 26.5. Add a
Node.js 22.23.2 fixture with the same steps as the 24.12 one, which on
22.x also lowers `using` to a runtime helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 15, 2026
The fix shipped in 26.2.0 and was backported to 24.18.0, not to 22.x.
Since the oxc-node#820 sync, the in-thread hooks return CommonJS source
that another hook supplied, so record the releases where require()
inside such a module can still fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 15, 2026
Guide: collect every difference that can need a change when moving from
tsx into one section: `paths` outside `include`, the JSX default and lone
`@jsxImportSource`, `.cts` files with module syntax, the Node.js range,
watch mode, eval and the REPL, `node --import tsx`, and other loaders.

RFC:
- Known Limitations: the in-thread window without nodejs/node#62920, and
  the project-local bin not forwarding a SIGINT sent to it alone.
- A CLI/loader contract change gets new entry file names, so an unaware
  `vp` falls back to the global loader.
- Source maps for node_modules, and their startup cost.
- Security: project code provides the loader, as for `vp` delegation.
- The daily upgrade can stay red while oxc-node needs a newer oxc than
  Rolldown.
- Phase 2 migrates tsx only, gated on the Node.js range.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 15, 2026
Node.js 22.22.3 and later use module.registerHooks(), decided by a
separate branch of canRegisterSyncHooks, and 22.x never gets
nodejs/node#62920, but no fixture ran that combination: the main fixture
pins 22.18 (module.register()) and the others 24.12 and 26.5. Add a
Node.js 22.23.2 fixture with the same steps as the 24.12 one, which on
22.x also lowers `using` to a runtime helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fengmk2 added a commit to voidzero-dev/vite-plus that referenced this pull request Oct 16, 2026
The fix shipped in 26.2.0 and was backported to 24.18.0, not to 22.x.
Since the oxc-node#820 sync, the in-thread hooks return CommonJS source
that another hook supplied, so record the releases where require()
inside such a module can still fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

esm Issues and PRs related to the ECMAScript Modules implementation. module Issues and PRs related to the module subsystem. needs-ci PRs that need a full CI run. review wanted PRs that need review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CJS module customized by synchronous customization hooks uses synthetic require with any use of --loader

6 participants